import * as SockJS from 'sockjs-client/dist/sockjs.js';
import * as Stomp from 'stompjs/lib/stomp.js';

/**
 * 根据用户传递的参数个数，自动判断参数的个数。3个参数为广播式，4个参数为点对点的。
 * 参数1：websocket的连接地址
 * 参数2：（广播式）为回调函数，（点对点）为订阅地址
 * 参数3：点对点下为回调函数，广播式下为连接参数项
 * 参数4：点对点下的参数项
 * 参数项的格式：{
 *   name:"token"
 * }
 * @returns {Promise<unknown>}
 * @constructor
 */
export function SWebSocket() {
  if (arguments.length === 3) {
    return broadcastWS(arguments[0], arguments[1], arguments[2]);
  } else if (arguments.length >= 4) {
    return p2pWS(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4] || []);
  } else {
  }
}

/**
 *
 * @param conUrl
 * @param subUrl
 * @param callback
 * @param options
 * @returns {Promise<unknown>}
 */
function p2pWS(conUrl, subUrl, callback, options, send) {
  return new Promise((resolve1, reject1) => {
    let stompClient = null;
    new Promise((resolve2, reject2) => {
      // 建立连接对象（还未发起连接）
      const socket = new SockJS(conUrl);
      // 获取 STOMP 子协议的客户端对象
      const stomp = Stomp;
      stompClient = stomp.Stomp.over(socket);
      stompClient.heartbeat.outgoing = 20000;  // client will send heartbeats every 20000ms
      stompClient.heartbeat.incoming = 20000;      // client does not want to receive heartbeats from the server
      stompClient.connect(options,
        function connectCallback(frame) {
          // 连接成功时（服务器响应 CONNECTED 帧）的回调方法
          console.log('连接websocket成功');
          resolve2();
        },
        function errorCallBack(error) {
          // 连接失败时（服务器响应 ERROR 帧）的回调方法
          console.log('连接websocket错误');
          reject1(error);
        });
    }).then(res => {
      stompClient.subscribe(subUrl, function (response) {
        callback(response);
      });
      /*
      * destination url 为服务器 controller中 @MessageMapping 中匹配的URL，字符串，必须参数；
      * headers 为发送信息的header，JavaScript 对象，可选参数；
      * body 为发送信息的 body，字符串，可选参数；
      * */
      if(Array.isArray(send) && send.length > 0) {
        stompClient.send(send[0], send[1] || {}, send[2] || '');
      }
      resolve1(stompClient);
    });
  });
}

/**
 *
 * @param conUrl
 * @param callback
 * @param options
 * @returns {Promise<unknown>}
 */
function broadcastWS(conUrl, callback, options) {
  let ws = null;
  return new Promise((resolve1, reject1) => {
    new Promise((resolve2, reject2) => {
      ws = new WebSocket(conUrl);
      ws.onopen = () => {
        console.log('连接成功');
        // if (!isNullOrUndefined(callback)) {
        //   callback();
        // }
        resolve2();
        resolve1(ws);
      };
      ws.onerror = () => {
        console.error('连接失败');
        reject1();
      };
      ws.onclose = () => {
        console.log('关闭');
      };
    }).then(res => {
      ws.onmessage = (event) => {
        callback(JSON.parse(event.data));
      };
    });
  });
}
